import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { finalize, map } from 'rxjs/operators';
import * as requestIp from 'request-ip';
import { SuccessResult } from '@/utils/res';
import { Reflector } from '@nestjs/core';
import { IS_RAW_RESPONSE_KEY } from '../decorators/raw-response.decorator';

@Injectable()
export class GlobalInterceptor implements NestInterceptor {
  private readonly logger = new Logger('GlobalInterceptor');

  constructor(private readonly reflector: Reflector) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const http = context.switchToHttp();
    const req = http.getRequest();
    const { body, params, query, url, method } = req;
    const now = Date.now();

    const isRawResponse = this.reflector.getAllAndOverride<boolean>(
      IS_RAW_RESPONSE_KEY,
      [context.getHandler(), context.getClass()],
    );

    return next.handle().pipe(
      map((data) => {
        if (isRawResponse) {
          return data;
        }
        return new SuccessResult(data);
      }),
      finalize(() => {
        this.logger.log(
          `${method} ${url} ${Date.now() - now}ms ${requestIp.getClientIp(req)} body:${JSON.stringify(body || {})} query:${JSON.stringify(query)} params:${JSON.stringify(params)}`,
        );
      }),
    );
  }
}
